Golang 对称加密算法
时间:2022-10-21 | 分类:编程笔记>Golang

对称加密算法是使用同一个密钥進行加密和解密的方法,常见的对称加密算法有:DES,3DES,AES,RC2,RC4, RC5。下面用golang来实现DES、3DES和AES加密算法。
package main import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/des" "encoding/base64" "errors" "fmt" ) func main() { //DES密钥 8个字节 key := "12345678" //3DES密钥 24个字节 //key = "abcdefig12345678gifedcba" //AES密钥,key长度:16、24、32 bytes 对应 AES-128、AES-192、AES-256 //key = "abcdefig12345678" keyBytes := []byte(key) strBytes := []byte("要加密的内容") fmt.Println("原数据:", strBytes) //进行加密 cipherArr, err := SCEncrypt(strBytes, keyBytes, "DES") if err != nil { fmt.Println(err) return } fmt.Println("加密后的数据:", cipherArr) oringinalBytes, err := SCDecrypt(cipherArr, keyBytes, "DES") if err != nil { fmt.Println(err) return } fmt.Println("解密后的数据:", oringinalBytes) fmt.Println("\n==========字符串方式加解密") str := "要加密的内容2" fmt.Println("原始数据:", str) cipherText, err := SCEncryptString(str, key, "DES") if err != nil { fmt.Println(err) return } fmt.Println("加密后的数据:", cipherText) oringinalText, err := SCDecryptString(cipherText, key, "DES") if err != nil { fmt.Println(err) return } fmt.Println("解密后的数据:", oringinalText) } //对称加密算法 (原数据, 密钥, 加密类型) func SCEncrypt(oringinalBytes, key []byte, scType string) ([]byte, error) { //1、实例化一个密码器block数据类型,(参数为密钥) var err error var block cipher.Block switch scType { case "DES": block, err = des.NewCipher(key) case "3DES": block, err = des.NewTripleDESCipher(key) case "AES": block, err = aes.NewCipher(key) } if err != nil { return nil, errors.New(fmt.Sprintf("密码器创建失败:%s", err)) } //要填充的区块个数 blockSize := block.BlockSize() //2、对明文填充(参数为原始字节和密码对象的区块个数) paddingBytes := PKCS5Pading(oringinalBytes, blockSize) fmt.Println("填充后的字节:", paddingBytes) //3、实例化CBC加密模式(参数为密码器和密钥) blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) fmt.Println("加密模式:", blockMode) //4、对填充后的明文字节加密(参数为加密字节和填充字节) cipherBytes := make([]byte, len(paddingBytes)) //用于接收加密后的字节 blockMode.CryptBlocks(cipherBytes, paddingBytes) return cipherBytes, nil } //对称解密 (加密数据, 密钥, 加密类型) func SCDecrypt(cipherBytes, key []byte, scType string) ([]byte, error) { //1、实例化一个密码器block数据类型,(参数为密钥) var err error var block cipher.Block switch scType { case "DES": block, err = des.NewCipher(key) case "3DES": block, err = des.NewTripleDESCipher(key) case "AES": block, err = aes.NewCipher(key) } if err != nil { return nil, errors.New(fmt.Sprintf("密码器创建失败:%s", err)) } //要填充的区块个数 blockSize := block.BlockSize() //2、实例化CBC解密模式(参数为密码器和密钥) blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) fmt.Println("解密模式:", blockMode) //3、对加密数据进行解密(参数为加密字节和填充字节) paddingBytes := make([]byte, len(cipherBytes)) //用于接收解密后的字节 blockMode.CryptBlocks(paddingBytes, cipherBytes) //4、去除填充的字节后获取到原数据 originalBytes := PKCS5UnPading(paddingBytes) return originalBytes, nil } //字符串方式加密 func SCEncryptString(originalText, key, scType string) (string, error) { cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key), scType) if err != nil { return "", nil } //把加密后的数据用base64编码为字符串 base64str := base64.StdEncoding.EncodeToString(cipherBytes) return base64str, nil } //字符串方式解密 func SCDecryptString(cipherText, key, scType string) (string, error) { cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText) cipherBytes, err := SCDecrypt(cipherBytes, []byte(key), scType) if err != nil { return "", nil } return string(cipherBytes), nil } //填充字节函数 //数字填充方式 func PKCS5Pading(data []byte, blockSize int) []byte { //填充内容 根据bolckSize的大小减去原始数据长度取余数 pading := blockSize - len(data)%blockSize fmt.Println("要填充的字节:", pading) //将pading转换为数组 arr1 := []byte{byte(pading)} //要填充pading的个数 arr2 := bytes.Repeat(arr1, pading) //返回填充后的数组 return append(data, arr2...) } //零位填充 func ZerosPading(data []byte, blockSize int) []byte { //填充内容 根据bolckSize的大小减去原始数据长度取余数 pading := blockSize - len(data)%blockSize fmt.Printf("要填充%d个0\n", pading) //填充0的数组 arr := bytes.Repeat([]byte{0}, pading) //返回填充后的数组 return append(data, arr...) } //去除填充字节函数 //去除数字填充 func PKCS5UnPading(data []byte) []byte { //获取最后一个元素,也就是要去除的数量 unPading := data[len(data)-1] //去除填充后的数组 result := data[:(len(data) - int(unPading))] return result } //去除零位填充 func ZerosUnPadding(data []byte) []byte { //把右侧的部分全部截取掉 return bytes.TrimRightFunc(data, func(r rune) bool { return r == 0 }) }